package edu.hubu.talentmanagementsystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.CaseFormat;
import edu.hubu.talentmanagementsystem.common.QnUploadUtils;
import edu.hubu.talentmanagementsystem.mapper.StaffRecruitmentRecordMapper;
import edu.hubu.talentmanagementsystem.mapper.context.MapperContext;
import edu.hubu.talentmanagementsystem.model.ext.*;
import edu.hubu.talentmanagementsystem.service.IStaffRecruitmentRecordService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import edu.hubu.talentmanagementsystem.common.EncodeOperation;
import edu.hubu.talentmanagementsystem.common.EncodeParam;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;

/**
 * @author moonlan
 * date 2021/3/2 下午8:45
 */
@SuppressWarnings(value = "unused")
@Service
@Transactional(rollbackFor = Exception.class)
public class StaffRecruitmentRecordServiceImpl extends ServiceImpl<StaffRecruitmentRecordMapper, StaffRecruitmentRecord> implements IStaffRecruitmentRecordService {

    private final MapperContext context;
    private final QnUploadUtils qnUploadUtils;

    @Value("${qiniu.cdn.prefix}")
    private String prefix;

    public StaffRecruitmentRecordServiceImpl(MapperContext context,QnUploadUtils qnUploadUtils) {
        this.context = context;
        this.qnUploadUtils = qnUploadUtils;
    }

    @Override
    public boolean deleteById(Integer id) {
        return context.getStaffRecruitmentRecordMapper().deleteById(id) > 0;
    }

    @Override
    @EncodeOperation
    public Optional<StaffRecruitmentRecord> insert(@EncodeParam StaffRecruitmentRecord record) {
        int insert = context.getStaffRecruitmentRecordMapper().insert(record);
        if (insert > 0) {
            return Optional.of(context.getStaffRecruitmentRecordMapper().selectById(record.primaryKeyValue()));
        }
        return Optional.empty();
    }

    @Override
    public Optional<StaffRecruitmentRecord> selectById(Integer id) {
        QueryWrapper<StaffRecruitmentRecord> wrapper = new QueryWrapper<>();
        LambdaQueryWrapper<StaffRecruitmentRecord> lambdaQueryWrapper = getColumnWrapper(wrapper.lambda()).eq(StaffRecruitmentRecord::getStaffRecruitmentRecordId, id);
        return Optional.of(context.getStaffRecruitmentRecordMapper().selectOne(lambdaQueryWrapper));
    }

    @Override
    public List<StaffRecruitmentRecord> selectAll(String order) {
        QueryWrapper<StaffRecruitmentRecord> wrapper = new QueryWrapper<>();
        if (!StringUtils.hasText(order)) {
            LambdaQueryWrapper<StaffRecruitmentRecord> select = getColumnWrapper(wrapper.lambda());
            return context.getStaffRecruitmentRecordMapper().selectList(select);
        }
        wrapper.orderByAsc(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, order));
        LambdaQueryWrapper<StaffRecruitmentRecord> select = getColumnWrapper(wrapper.lambda());
        return context.getStaffRecruitmentRecordMapper().selectList(select);
    }

    @Override
    public Page<StaffRecruitmentRecord> selectAllPaged( Integer currentPage,
             Integer pageSize, String order) {
        QueryWrapper<StaffRecruitmentRecord> wrapper = new QueryWrapper<>();
        Page<StaffRecruitmentRecord> page = new Page<>(currentPage, pageSize);
        if (!StringUtils.hasText(order)) {
            LambdaQueryWrapper<StaffRecruitmentRecord> select = getColumnWrapper(wrapper.lambda());
            return context.getStaffRecruitmentRecordMapper().selectPage(page, select);
        }
        wrapper.orderByAsc(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, order));
        LambdaQueryWrapper<StaffRecruitmentRecord> select = getColumnWrapper(wrapper.lambda());
        return context.getStaffRecruitmentRecordMapper().selectPage(page, select);
    }

    private LambdaQueryWrapper<StaffRecruitmentRecord> getColumnWrapper(LambdaQueryWrapper<StaffRecruitmentRecord> wrapper) {
        return wrapper.select(
                StaffRecruitmentRecord::getStaff
                    ,
                StaffRecruitmentRecord::getResume
                    ,
                StaffRecruitmentRecord::getStaffRecruitmentRecordId
                    ,
                StaffRecruitmentRecord::getStaffRecruitmentRecordStaffId
                    ,
                StaffRecruitmentRecord::getStaffRecruitmentRecordResumeId
        );
    }

    @Override
    public Page<StaffRecruitmentRecord> selectLikePaged( Integer currentPage,
             Integer pageSize, StaffRecruitmentRecord record, String order) {
        Page<StaffRecruitmentRecord> page = new Page<>(currentPage, pageSize);
        QueryWrapper<StaffRecruitmentRecord> wrapper = new QueryWrapper<>();
        if (!StringUtils.hasText(order)) {
            return context.getStaffRecruitmentRecordMapper().selectPage(page, getColumnWrapper(getQueryWrapper(wrapper, record)));
        }
        wrapper.orderByAsc(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, order));
        return context.getStaffRecruitmentRecordMapper().selectPage(page, getColumnWrapper(getQueryWrapper(wrapper, record)));
    }

    private LambdaQueryWrapper<StaffRecruitmentRecord> getQueryWrapper(QueryWrapper<StaffRecruitmentRecord>wrapper, StaffRecruitmentRecord record) {
        LambdaQueryWrapper<StaffRecruitmentRecord> lambda = wrapper.lambda();
        if (record.getStaff() != null) {
            lambda = lambda.eq(StaffRecruitmentRecord::getStaff,record.getStaff());
        }
        if (record.getResume() != null) {
            lambda = lambda.eq(StaffRecruitmentRecord::getResume,record.getResume());
        }
        if (record.getStaffRecruitmentRecordId() != null) {
            lambda = lambda.eq(StaffRecruitmentRecord::getStaffRecruitmentRecordId,record.getStaffRecruitmentRecordId());
        }
        if (record.getStaffRecruitmentRecordStaffId() != null) {
            lambda = lambda.eq(StaffRecruitmentRecord::getStaffRecruitmentRecordStaffId,record.getStaffRecruitmentRecordStaffId());
        }
        if (record.getStaffRecruitmentRecordResumeId() != null) {
            lambda = lambda.eq(StaffRecruitmentRecord::getStaffRecruitmentRecordResumeId,record.getStaffRecruitmentRecordResumeId());
        }
        return lambda;
    }

    public int count(StaffRecruitmentRecord record) {
        return context.getStaffRecruitmentRecordMapper().selectCount(getQueryWrapper(new QueryWrapper<>(), record));
    }

    @Override
    @EncodeOperation
    public Optional<StaffRecruitmentRecord> updateById(Integer id, @EncodeParam StaffRecruitmentRecord record) {
        record.setStaffRecruitmentRecordId(id);
        int update = context.getStaffRecruitmentRecordMapper().updateById(record);
        if (update > 0) {
            QueryWrapper<StaffRecruitmentRecord> wrapper = new QueryWrapper<>();
            LambdaQueryWrapper<StaffRecruitmentRecord> lambdaQueryWrapper = getColumnWrapper(wrapper.lambda()).eq(StaffRecruitmentRecord::getStaffRecruitmentRecordId, id);
            return Optional.of(context.getStaffRecruitmentRecordMapper().selectOne(getColumnWrapper(lambdaQueryWrapper)));
        }

        return Optional.empty();
    }

    @Override
    public Map<String, Object> selectRecruitmentInfoByCompanyId(Integer currentPage, Integer pageSize, Integer companyId) {
        Page<StaffRecruitmentRecord> staffRecruitmentRecordPage = context.getStaffRecruitmentRecordMapper().selectPage(new Page<>(currentPage, pageSize),
                new QueryWrapper<StaffRecruitmentRecord>().eq("staff_recruitment_record_company_recruitment_id", companyId));
        List<StaffRecruitmentRecord> staffRecruitmentRecords = staffRecruitmentRecordPage.getRecords();
        List<Staff> staffList = new ArrayList<>();
        List<String> departmentList = new ArrayList<>();
        List<String> positionList = new ArrayList<>();
        for (StaffRecruitmentRecord staffRecruitmentRecord : staffRecruitmentRecords) {
            Staff staff = context.getStaffMapper().selectById(staffRecruitmentRecord.getStaffRecruitmentRecordStaffId());
            staff.setStaffPwd(null);
            staffList.add(staff);
            CompanyRecruitment recruitment = context.getCompanyRecruitmentMapper().selectOne(new QueryWrapper<CompanyRecruitment>().eq("company_recruitment_id", staffRecruitmentRecord.getStaffRecruitmentRecordCompanyRecruitmentId()));
            departmentList.add(context.getDepartmentMapper().selectOne(new QueryWrapper<Department>().eq("department_id",recruitment.getCompanyRecruitmentDepartmentId())).getDepartmentName());
            positionList.add(context.getCompanyPositionMapper().selectOne(new QueryWrapper<CompanyPosition>().eq("company_position_id",recruitment.getCompanyRecruitmentPositionId())).getCompanyPositionName());
        }
        Map<String,Object> result = new HashMap<>();
        result.put("currentPage",staffRecruitmentRecordPage.getCurrent());
        result.put("pageSize",staffRecruitmentRecordPage.getSize());
        result.put("total",staffRecruitmentRecordPage.getTotal());
        result.put("staffRecruitmentRecords",staffRecruitmentRecords);
        result.put("staffList",staffList);
        result.put("departmentList",departmentList);
        result.put("positionList",positionList);
        return result;
    }

    @Override
    public Map<String, Object> selectRecruitmentInfoByCompanyAndDepartmentId(Integer currentPage, Integer pageSize, Integer companyId, Integer department_id) {
        List<CompanyRecruitment> companyRecruitmentList = context.getCompanyRecruitmentMapper().selectList(new QueryWrapper<CompanyRecruitment>().eq("company_recruitment_company_id", companyId).eq("company_recruitment_department_id", department_id));
        List<Integer> companyRecruitmentIdList = new ArrayList<>();
        for (CompanyRecruitment companyRecruitment : companyRecruitmentList) {
            companyRecruitmentIdList.add(companyRecruitment.getCompanyRecruitmentId());
        }
        Page<StaffRecruitmentRecord> staffRecruitmentRecordPage = context.getStaffRecruitmentRecordMapper().selectPage(new Page<>(currentPage, pageSize), new QueryWrapper<StaffRecruitmentRecord>().in("staff_recruitment_record_company_recruitment_id", companyRecruitmentIdList));
        List<StaffRecruitmentRecord> staffRecruitmentRecords = staffRecruitmentRecordPage.getRecords();
        List<Staff> staffList = new ArrayList<>();
        List<String> positionList = new ArrayList<>();
        for (StaffRecruitmentRecord staffRecruitmentRecord : staffRecruitmentRecords) {
            Staff staff = context.getStaffMapper().selectById(staffRecruitmentRecord.getStaffRecruitmentRecordStaffId());
            staff.setStaffPwd(null);
            staffList.add(staff);
            CompanyRecruitment recruitment = context.getCompanyRecruitmentMapper().selectOne(new QueryWrapper<CompanyRecruitment>().eq("company_recruitment_id", staffRecruitmentRecord.getStaffRecruitmentRecordCompanyRecruitmentId()));
            positionList.add(context.getCompanyPositionMapper().selectOne(new QueryWrapper<CompanyPosition>().eq("company_position_id",recruitment.getCompanyRecruitmentPositionId())).getCompanyPositionName());
        }
        Map<String,Object> result = new HashMap<>();
        result.put("currentPage",staffRecruitmentRecordPage.getCurrent());
        result.put("pageSize",staffRecruitmentRecordPage.getSize());
        result.put("total",staffRecruitmentRecordPage.getTotal());
        result.put("staffRecruitmentRecords",staffRecruitmentRecords);
        result.put("staffList",staffList);
        result.put("positionList",positionList);
        return result;
    }

    @Override
    public boolean commitResume(Integer staffId, Integer companyId, MultipartFile file, Integer recruitmentId) {
        String url = qnUploadUtils.upload(file);

        Resume staffResume = context.getResumeMapper().selectOne(new QueryWrapper<Resume>().eq("resume_staff_id", staffId));
        Integer resumeId;
        if (staffResume == null){
            Resume resume = new Resume();
            resume.setResumeStaffId(staffId)
                    .setResumeUrl(url);
            context.getResumeMapper().insert(resume);
            Resume newResume =  context.getResumeMapper().selectOne(new QueryWrapper<Resume>().eq("resume_staff_id", staffId));
            resumeId = newResume.getResumeId();
        }else {
            staffResume.setResumeUrl(url);
            context.getResumeMapper().update(staffResume,new QueryWrapper<Resume>().eq("resume_staff_id",staffId));
            resumeId = staffResume.getResumeId();
        }
        StaffRecruitmentRecord staffRecruitmentRecord = new StaffRecruitmentRecord();
        staffRecruitmentRecord.setStaffRecruitmentRecordStaffId(staffId)
        .setStaffRecruitmentRecordResumeId(resumeId)
        .setStaffRecruitmentRecordCompanyId(companyId)
        .setStaffRecruitmentRecordCompanyRecruitmentId(recruitmentId);
        return context.getStaffRecruitmentRecordMapper().insert(staffRecruitmentRecord) > 0;
    }
}
